#include "StdAfx.h"
#include "dead6502v4.h"

enum addrmodes2 {er=0,no,ab,ax,ay,ac,im,ix,iy,in,re,zp,zx,zy};

static u8 addrtable[256] =
	{
   no,ix,er,er,er,zp,zp,er, //00-07
	no,im,ac,er,er,ab,ab,er, //08-0f
   re,iy,er,er,er,zx,zx,er, //10-17
	no,ay,er,er,er,ax,ax,er, //18-1f
   ab,ix,er,er,zp,zp,zp,er, //20-27
	no,im,ac,er,ab,ab,ab,er, //28-2f
   re,iy,er,er,er,zx,zx,er, //30-37
	no,ay,er,er,er,ax,ax,er, //38-3f
   no,ix,er,er,er,zp,zp,er, //40-47
	no,im,ac,er,ab,ab,ab,er, //48-4f
   re,iy,er,er,er,zx,zx,er, //50-57
	no,ay,er,er,er,ax,ax,er, //58-5f
   no,ix,er,er,er,zp,zp,er, //60-67
	no,im,ac,er,in,ab,ab,er, //68-6f
   re,iy,er,er,er,zx,zx,er, //70-77
	no,ay,er,er,er,ax,ax,er, //78-7f
 	er,ix,er,er,zp,zp,zp,er, //80-87
	no,er,no,er,ab,ab,ab,er, //88-8f
   re,iy,er,er,zx,zx,zy,er, //90-97
	no,ay,no,er,er,ax,er,er, //98-9f
   im,ix,im,er,zp,zp,zp,er, //a0-a7
	no,im,no,er,ab,ab,ab,er, //a8-af
   re,iy,er,er,zx,zx,zy,er, //b0-b7
	no,ay,no,er,ax,ax,ay,er, //b8-bf
   im,ix,er,er,zp,zp,zp,er, //c0-c7
	no,im,no,er,ab,ab,ab,er, //c8-cf
   re,iy,er,er,er,zx,zx,er, //d0-d7
	no,ay,er,er,er,ax,ax,er, //d8-df
   im,ix,er,er,zp,zp,zp,er, //e0-e7
	no,im,no,er,ab,ab,ab,er, //e8-ef
   re,iy,er,er,er,zx,zx,er, //f0-f7
	no,ay,er,er,er,ax,ax,er  //f8-ff
   };
static u8 oplength[256];

void CDead6502v4::SetMachine(CMachine *m)
{
MachinePtr = m;
}

void CDead6502v4::SetOp(ReadFunc *r)
{
int i;

for(i=0;i<32;i++)
	c6502.opptr[i] = r;
}

void CDead6502v4::SetRead(ReadFunc *r)
{
int i;

SetOp(r);
for(i=0;i<32;i++)
	c6502.readptr[i] = r;
}

void CDead6502v4::SetWrite(WriteFunc *w)
{
int i;

for(i=0;i<32;i++)
	c6502.writeptr[i] = w;
}

void CDead6502v4::SetUser(void *u)
{
c6502.user = u;
}

void CDead6502v4::Init()
{
int i;

for(i=0;i<32;i++)
	{
	c6502.opptr[i] = 0;
	c6502.readptr[i] = 0;
	c6502.writeptr[i] = 0;
	c6502.ramptr[i] = 0;
	c6502.romptr[i] = 0;
	}
for(i=0;i<256;i++)
	{
	switch(addrtable[i])
		{
		case er:
		case no:
		case ac:oplength[i] = 1;break;
		case im:
		case ix:
		case iy:
		case re:
		case zp:
		case zx:
		case zy:oplength[i] = 2;break;
		case ab:
		case ax:
		case ay:
		case in:oplength[i] = 3;break;
		}
	}
}

void CDead6502v4::Reset()
{
c6502.Reset();
}

void CDead6502v4::IRQ()
{
c6502.IRQ();
}

void CDead6502v4::NMI()
{
c6502.NMI();
}

void CDead6502v4::SetOpPage(int p,u8 *d)
{
c6502.opromptr[p] = d;
}

void CDead6502v4::SetReadPage(int p,u8 *d)
{
c6502.romptr[p] = d;
}

void CDead6502v4::SetWritePage(int p,u8 *d)
{
c6502.ramptr[p] = d;
}

void CDead6502v4::SetPage(int p,u8 *d)
{
SetReadPage(p,d);
SetWritePage(p,d);
}

u32 CDead6502v4::Execute(u32 c)
{
u32 ret = 0;
u64 s;

while(ret < c)
	{
	s = c6502.cycle;
	CurPC = c6502.pc;
	c6502.ExecuteOpcode();
	ret += (u32)(c6502.cycle - s);
	if(c6502.badopcode)
		ret |= 0x80000000;
	}
CurPC = c6502.pc;
return(ret);
}

u8 CDead6502v4::Read(u32 addr)
{
return(c6502.MemRead(addr));
}

void CDead6502v4::Write(u32 addr,u8 data)
{
c6502.MemWrite(addr,data);
}

u32 CDead6502v4::GetPC()
{
return(CurPC);
}

u8 CDead6502v4::GetOpcode()
{
return(Read(CurPC));
}		

u32 CDead6502v4::GetNextOpcodePC()
{
return(CurPC + oplength[GetOpcode()]);
}

u32 CDead6502v4::GetCurrentOpcodePC()
{
return(CurPC);
}

u32 CDead6502v4::GetLastRead()
{
return(c6502.lastread);
}

u32 CDead6502v4::GetLastWrite()
{
return(c6502.lastwrite);
}

void CDead6502v4::SaveState(CState *s)
{
s->Write8(c6502.a);
s->Write8(c6502.x);
s->Write8(c6502.y);
s->Write8(c6502.s);
s->Write8(c6502.f);
s->Write16((u16)c6502.pc);
}

void CDead6502v4::LoadState(CState *s)
{
c6502.a = s->Read8();
c6502.x = s->Read8();
c6502.y = s->Read8();
c6502.s = s->Read8();
c6502.f = s->Read8();
c6502.pc = s->Read16();
}

int CDead6502v4::InsideIRQ()
{
return(c6502.irq_active);
}

int CDead6502v4::InsideNMI()
{
return(c6502.nmi_active);
}

char *CDead6502v4::GenerateRegData(char *dest)
{
sprintf(dest,
"$%04X\n"
"$%02X\n"
"$%02X\n"
"$%02X\n"
"$%02X\n"
"$%02X\n"
"\n"
"\n"
"$%04X\n"
"$%04X\n"
"$%04X\n",
	c6502.pc,c6502.a,c6502.x,c6502.y,c6502.s,c6502.f,
	Read(0xFFFA) | (Read(0xFFFB) << 8),
	Read(0xFFFE) | (Read(0xFFFF) << 8),
	Read(0xFFFC) | (Read(0xFFFD) << 8)
);
return(dest);
}
